package tester;

import java.io.*;
import java.net.*;
import java.util.*;

public class Tester extends Thread {
        // The ServerSocket we'll use for accepting new connections
        private ServerSocket ss;
        private int port;
        private TesterGUI gui;
        private DataOutputStream dout;
        //private static int port = 4444;
        // A mapping from sockets to DataOutputStreams. This will
        // help us avoid having to create a DataOutputStream each time
        // we want to write to a stream.
        private Hashtable outputStreams = new Hashtable();
        // Constructor and while-accept loop all in one.
        public Tester( TesterGUI gui, int port ) throws IOException {
                // All we have to do is listen
                this.port = port;
                this.gui = gui;
                start();
        }
       
        public void run(){
                try {
                        listen(port);
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
        }
       
        private void listen( int port ) throws IOException {
                // Create the ServerSocket
                ss = new ServerSocket( port );
                // Tell the world we're ready to go
                System.out.println( "Listening on "+ss );
                // Keep accepting connections forever
                while (true) {
                        // Grab the next incoming connection
                        Socket s = ss.accept();
                        // Tell the world we've got it
                        System.out.println( "Connection from "+s );
                        // Create a DataOutputStream for writing data to the
                        // other side
                        dout = new DataOutputStream( s.getOutputStream() );
                        // Save this stream so we don't need to make it again
                        outputStreams.put( s, dout );
                        // Create a new thread for this connection, and then forget
                        // about it
                        new TesterThread( this, s );
                }
        }
        // Get an enumeration of all the OutputStreams, one for each client
        // connected to us
        Enumeration getOutputStreams() {
                return outputStreams.elements();
        }
        // Send a message to all clients (utility routine)
    	// Gets called when the user types something
    	public void sendMessage( String message ){
    		try {
    			log(getClass().toString() +" Sending message: " + message);
    			for (int i = 0; i < message.length(); i++){
    				dout.writeChar(message.charAt(i));
    				try {
    					Thread.sleep(20);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		} catch( IOException ie ) { System.out.println( ie ); }
    	}
        // Remove a socket, and it's corresponding output stream, from our
        // list. This is usually called by a connection thread that has
        // discovered that the connectin to the client is dead.
        void removeConnection( Socket s ) {
                // Synchronize so we don't mess up sendToAll() while it walks
                // down the list of all output streamsa
                synchronized( outputStreams ) {
                        // Log in the console
                        System.out.println( "Removing connection to " + s );
                        //Log in the GUI
                        gui.log("Removing connection from " + s);
                        // Remove it from our hashtable/list
                        outputStreams.remove( s );
                        // Make sure it's closed
                        try {
                                s.close();
                        } catch( IOException ie ) {
                                System.out.println( "Error closing "+s );
                                ie.printStackTrace();
                        }
                }
        }
       
        public void log (char cmsg){
        	log(Character.toString(cmsg));        		
        }
        
        public void log(String msg){
                gui.log(msg);
        }
}

